package system1

import (
	"encoding/json"
	"fmt"
	"reflect"
	"strconv"

	simplejson "github.com/bitly/go-simplejson"
	"github.com/flipped-aurora/gin-vue-admin/server/global"
	"github.com/flipped-aurora/gin-vue-admin/server/model/system"
	"github.com/flipped-aurora/gin-vue-admin/server/model/system1"
	system1Req "github.com/flipped-aurora/gin-vue-admin/server/model/system1/request"
	"gorm.io/gorm"
)

type WorkflowDataService struct {
}

// CreateWorkflowData 创建审批数据记录
// Author [piexlmax](https://github.com/piexlmax)
func (WorkflowDataService *WorkflowDataService) CreateWorkflowData(WorkflowData *system1.WorkflowData) (err error) {
	err = global.GVA_DB.Create(WorkflowData).Error
	return err
}

// DeleteWorkflowData 删除审批数据记录
// Author [piexlmax](https://github.com/piexlmax)
func (WorkflowDataService *WorkflowDataService) DeleteWorkflowData(ID string, userID uint) (err error) {
	err = global.GVA_DB.Transaction(func(tx *gorm.DB) error {
		if err := tx.Model(&system1.WorkflowData{}).Where("id = ?", ID).Update("deleted_by", userID).Error; err != nil {
			return err
		}
		if err = tx.Delete(&system1.WorkflowData{}, "id = ?", ID).Error; err != nil {
			return err
		}
		return nil
	})
	return err
}

// DeleteWorkflowDataByIds 批量删除审批数据记录
// Author [piexlmax](https://github.com/piexlmax)
func (WorkflowDataService *WorkflowDataService) DeleteWorkflowDataByIds(IDs []string, deleted_by uint) (err error) {
	err = global.GVA_DB.Transaction(func(tx *gorm.DB) error {
		if err := tx.Model(&system1.WorkflowData{}).Where("id in ?", IDs).Update("deleted_by", deleted_by).Error; err != nil {
			return err
		}
		if err := tx.Where("id in ?", IDs).Delete(&system1.WorkflowData{}).Error; err != nil {
			return err
		}
		return nil
	})
	return err
}

// UpdateWorkflowData 更新审批数据记录
// Author [piexlmax](https://github.com/piexlmax)
func (WorkflowDataService *WorkflowDataService) UpdateWorkflowData(WorkflowData system1.WorkflowData) (err error) {
	err = global.GVA_DB.Save(&WorkflowData).Error
	return err
}

// GetWorkflowData 根据ID获取审批数据记录
// Author [piexlmax](https://github.com/piexlmax)
func (WorkflowDataService *WorkflowDataService) GetWorkflowData(ID string) (WorkflowData system1.WorkflowData, err error) {
	err = global.GVA_DB.Preload("WorkflowLog", func(db *gorm.DB) *gorm.DB { return db.Order("created_at DESC") }).Where("id = ?", ID).First(&WorkflowData).Error
	return
}

// GetWorkflowDataInfoList 分页获取审批数据记录
// Author [piexlmax](https://github.com/piexlmax)
func (WorkflowDataService *WorkflowDataService) GetWorkflowDataInfoList(info system1Req.WorkflowDataSearch) (list []system1.WorkflowData, total int64, err error) {
	limit := info.PageSize
	offset := info.PageSize * (info.Page - 1)
	// 创建db
	db := global.GVA_DB.Model(&system1.WorkflowData{})
	var WorkflowDatas []system1.WorkflowData
	// 如果有条件搜索 下方会自动创建搜索语句
	if info.StartCreatedAt != nil && info.EndCreatedAt != nil {
		db = db.Where("created_at BETWEEN ? AND ?", info.StartCreatedAt, info.EndCreatedAt)
	}
	if info.State != "" {
		db = db.Where("state = ?", info.State)
	}
	err = db.Count(&total).Error
	if err != nil {
		return
	}

	if limit != 0 {
		db = db.Limit(limit).Offset(offset)
	}

	err = db.Order("created_at DESC,updated_at DESC").Find(&WorkflowDatas).Error
	return WorkflowDatas, total, err
}

/*
****************************************************************************

	"nodeConfig": {
		"nodeName": "发起人",//节点名称
		"type": 0,// 0 发起人 1审批 2抄送 3条件 4路由
		"priorityLevel": "",// 条件优先级
		"settype": "",// 审批人设置 1指定成员 2主管 4发起人自选 5发起人自己 7连续多级主管
		"selectMode": "", //审批人数 1选一个人 2选多个人
		"selectRange": "", //选择范围 1.全公司 2指定成员 2指定角色
		"directorLevel": "", //审批终点  最高层主管数
		"examineMode": "", //多人审批时采用的审批方式 1依次审批 2会签
		"noHanderAction": "",//审批人为空时 1自动审批通过/不允许发起 2转交给审核管理员
		"examineEndDirectorLevel": "", //审批终点 第n层主管
		"ccSelfSelectFlag": "", //允许发起人自选抄送人
		"conditionList": [], //当审批单同时满足以下条件时进入此流程
		"nodeUserList": [], //操作人

*****************************************************************************
*/
func iCurrNode(nodeData *simplejson.Json) (currNode *simplejson.Json, currPath []string) {
	//process data here
	var mPath []string
	//if nodeConfig exist go into it
	//cNode := nodeData.Get("nodeConfig")
	if cNode, ok := nodeData.CheckGet("nodeConfig"); ok {
		fmt.Println("found nodeConfig go into it")
		//fmt.Println("nodeConfig", cNode)
		currPath = append(currPath, "nodeConfig")
		currNode, mPath = iCurrNode(cNode)
		currPath = append(currPath, mPath...)
		return
	}

	//try to recurrent call
	mType, err := nodeData.Get("type").Int()
	if err != nil {
		fmt.Println("err:", err)
		return
	}
	if mType == 0 {
		fmt.Println("type 发起人")
		fmt.Println("nodeUserList", nodeData.Get("nodeUserList"))
		cNode := nodeData.Get("childNode")
		currPath = append(currPath, "childNode")
		if cNode != nil {
			currNode, mPath = iCurrNode(cNode)
		}
		currPath = append(currPath, mPath...)
	} else if mType == 1 {
		fmt.Println("type 审核人")
		bApproved, err1 := nodeData.Get("approved").Bool()
		if err1 != nil {
			fmt.Println("还未审批")
			currNode = nodeData
			return
		} else {
			if !bApproved {
				fmt.Println("Rejected by this approver")
				return currNode, mPath
			} else {
				if _, ok := nodeData.CheckGet("childNode"); ok {
					currPath = append(currPath, "childNode")
					currNode, mPath = iCurrNode(nodeData.Get("childNode"))
					currPath = append(currPath, mPath...)
				}
			}
		}
	}
	if nodeData.Get("childNode") == nil {
		fmt.Println("type 走到审批尽头了")
		return
	}
	//fmt.Println("final return currNode:", currNode)
	return
}

// GetSys_departmentManager 根据userId获取managerId
// Author [piexlmax](https://github.com/piexlmax)
func iGetManager(userId int) (managerId int, err error) {
	var sysuser system.SysUser
	var department system1.Sys_department
	err = global.GVA_DB.Where("id = ?", userId).First(&sysuser).Error
	if err == nil {
		err = global.GVA_DB.Where("id = ?", sysuser.DepartmentId).First(&department).Error
		managerId = department.ManagerUserId
		fmt.Println("uid", userId, " manager is ", managerId)
	} else {
		fmt.Println("err:", err)
	}
	return
}

func iCurrOwners(WorkflowData system1.WorkflowData, nodeData *simplejson.Json) (currOwners *simplejson.Json) {
	currNode, currPath := iCurrNode(nodeData)
	//currNodeByPath := nodeData.GetPath(currPath...)
	//fmt.Println("currNode      :", currNode)
	//fmt.Println("currNodeByPath:", currNodeByPath)
	fmt.Println("currPath", currPath)

	var mType int
	if currNode == nil {
		return
	}
	if _, ok := currNode.CheckGet("settype"); ok {
		var err error
		mType, err = currNode.Get("settype").Int()
		if err != nil {
			fmt.Println("err:", err)
			return
		}
	} else {
		return
	}

	fmt.Println("mType", mType)
	if mType == 2 {
		var sysuser system.SysUser
		fmt.Println("nodeUserList [settype 主管]")
		uid, _ := iGetManager(WorkflowData.SubmitterId)
		fmt.Println("get userid", uid)
		err := global.GVA_DB.Where("id = ?", uid).First(&sysuser).Error
		if err == nil {
			jsonStr := "[{"
			jsonStr += "\"name\":" + "\"" + sysuser.NickName + "\"" + ", "
			jsonStr += "\"targetId\":" + string(strconv.Itoa(int(sysuser.ID))) + ", "
			jsonStr += "\"type\":" + "1"
			jsonStr += "}]"
			jData, err1 := simplejson.NewJson([]byte(jsonStr))
			if err1 != nil {
				fmt.Println("err1", err1)
			}
			currOwners = jData
			return
		}
	} else {
		fmt.Println("nodeUserList", currNode.Get("nodeUserList"))
	}
	currOwners = currNode.Get("nodeUserList")
	return
}

// GetWorkflowData 根据ID获取审批数据记录
// Author [piexlmax](https://github.com/piexlmax)
func (WorkflowDataService *WorkflowDataService) GetCurrentOwners(WorkflowData system1.WorkflowData) (currOwners *simplejson.Json, err error) {
	jsonStr := WorkflowData.Flow
	js, err := simplejson.NewJson([]byte(jsonStr))
	if err != nil {
		fmt.Println("JsonToMapDemo err:", err)
	}
	currOwners = iCurrOwners(WorkflowData, js)
	return
}

// GetWorkflowData 根据ID获取审批数据记录
// Author [piexlmax](https://github.com/piexlmax)
func (WorkflowDataService *WorkflowDataService) UpdateCurrentOwners(WorkflowData system1.WorkflowData) {
	jsonStr := WorkflowData.Flow
	js, err := simplejson.NewJson([]byte(jsonStr))
	if err != nil {
		fmt.Println("JsonToMapDemo err:", err)
	}
	currOwners := iCurrOwners(WorkflowData, js)
	fmt.Println("currOwners sdafdf", currOwners)
	//ownerArray, err := currOwners.Array()
	db := global.GVA_DB
	db.Exec("delete from workflow_owner where workflow_data_id=?", WorkflowData.ID)
	//when currOwners is nil means the process end. current action is final result
	if currOwners == nil {
		return
	}
	// 获取到key为tags的map
	tags, _ := currOwners.Array()
	fmt.Println("tags", tags)
	for _, value := range tags {
		// fmt.Println(value["name"]) //会报错
		// 要先使用断言  否则报错
		WorkflowOwner := new(system1.WorkflowOwner)

		tagname, _ := value.(map[string]interface{})
		fmt.Println("type_is", reflect.TypeOf((tagname["targetId"])))
		mVal, _ := tagname["targetId"].(json.Number).Int64()
		WorkflowOwner.CreatedBy = 1
		WorkflowOwner.Userid = int(mVal)
		WorkflowOwner.WorkflowDataId = int(WorkflowData.ID)
		fmt.Println("WorkflowOwner", WorkflowOwner)
		err = global.GVA_DB.Create(&WorkflowOwner).Error
		if err != nil {
			fmt.Println("err:", err)
		}
		fmt.Println(tagname["name"])
		fmt.Println(tagname["targetId"])
		fmt.Println(tagname["type"])
	}
	//return
}

// WorkflowDataApprove 通过审批
// Author [piexlmax](https://github.com/piexlmax)
func (WorkflowDataService *WorkflowDataService) WorkflowDataApprove(WorkflowData system1.WorkflowData, commnet string, userid uint) (err error) {
	jsonStr := WorkflowData.Flow
	js, err := simplejson.NewJson([]byte(jsonStr))
	if err != nil {
		fmt.Println("JsonToMapDemo err:", err)
		return err
	}

	_, currPath := iCurrNode(js)
	path2Set := append(currPath, "approved")
	js.SetPath(path2Set, true)
	jByte, _ := js.Encode()
	//fmt.Println("jByte", string(jByte))
	fmt.Println("WorkflowDataApprove currPath", currPath)
	WorkflowData.Flow = string(jByte)
	fmt.Println("newFlowData", string(jByte))
	err = global.GVA_DB.Save(WorkflowData).Error
	return err
}

// WorkflowDataReject 驳回审批
// Author [piexlmax](https://github.com/piexlmax)
func (WorkflowDataService *WorkflowDataService) WorkflowDataReject(WorkflowData system1.WorkflowData, commnet string, userid uint) (err error) {
	jsonStr := WorkflowData.Flow
	js, err := simplejson.NewJson([]byte(jsonStr))
	if err != nil {
		fmt.Println("JsonToMapDemo err:", err)
		return err
	}

	_, currPath := iCurrNode(js)
	path2Set := append(currPath, "approved")
	js.SetPath(path2Set, false)
	jByte, _ := js.Encode()
	//fmt.Println("jByte", string(jByte))
	fmt.Println("WorkflowDataApprove currPath", currPath)
	WorkflowData.Flow = string(jByte)
	fmt.Println("newFlowData", string(jByte))
	err = global.GVA_DB.Save(WorkflowData).Error
	return err
}
